package com.atguigu.gmall.seckill.mq;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.config.mq.service.MqService;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.msg.SeckillOrderQueueMsg;
import com.atguigu.gmall.order.entity.OrderDetail;
import com.atguigu.gmall.order.entity.OrderInfo;
import com.atguigu.gmall.seckill.entity.SeckillGoods;
import com.atguigu.gmall.seckill.service.SeckillBizService;
import com.atguigu.gmall.seckill.service.SeckillGoodsService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Return
 * @Author https://weiranyi.github.io
 * @Date Created in 2022-12-27 08:39
 **/
@Slf4j
@Component
public class SeckillQueueListear {
    @Autowired
    MqService mqService;
    @Autowired
    SeckillGoodsService seckillGoodsService;
    @Autowired
    SeckillBizService seckillBizService;
    @Autowired
    StringRedisTemplate redisTemplate;

    @RabbitListener(
            bindings = {
                    @QueueBinding(
                            value = @Queue(value = MqConst.SECKILL_LINED_UP_QUEUE, durable = "true", autoDelete = "false", exclusive = "false"),
                            exchange = @Exchange(value = MqConst.SECKILL_EVENT_EXCHANGE, durable = "true", autoDelete = "false"),
                            key = MqConst.SECKILL_QUEUE_RK
                    )
            }
    )
    public void queue(Message message, Channel channel) {
        log.info("秒杀排队消息抵达，开始扣减库存···");
        /**
         * seckill:order:code码 = JSON.toJSONString(OrderInfo)
         * （1）扣数据库成功，生成临时单
         *   - 1）orderInfo如果有用户收货地址，证明已经秒杀过了 218状态
         *   - 2）orderInfo如果没有用户收货地址，证明刚刚才下单，去完善订单信息 215状态
         * （2）口数据库失败，提示没有库存
         */
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            SeckillOrderQueueMsg msg = mqService.getMessageContent(message, SeckillOrderQueueMsg.class);
            Long skuId = msg.getSkuId();
            Long userId = msg.getUserId();
            String code = msg.getCode();
            // 扣数据库库存
            SeckillGoods goodsDetail = seckillBizService.getSeckillGoodsDetails(skuId);
            // 准备订单数据
            OrderInfo orderInfo = prepareOrderInfo(goodsDetail,userId);
            // 借助数据库无符号约束，扣到负数就会抛出异常
            boolean isSuccess = seckillGoodsService.updateStockDecrOne(goodsDetail.getId());
            if (isSuccess) {
                // 数据库成功,redis保存临时单数据(可以更新redis数据，扣减)
                redisTemplate.opsForValue().set(RedisConst.SECKILL_ORDER_CACHE + code, JSON.toJSONString(orderInfo), 2, TimeUnit.DAYS);
            } else {
                // 扣失败了，redis保存一个x
                redisTemplate.opsForValue().set(RedisConst.SECKILL_ORDER_CACHE + code, "x", 2, TimeUnit.DAYS);
            }
            channel.basicAck(deliveryTag,false);
        } catch (Exception e) {
            mqService.retry(message, channel, MqConst.ORDER_RETRY_COUNT);
        }
    }

    private OrderInfo prepareOrderInfo(SeckillGoods goodsDetail, Long userId) {
        // 准备订单
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserId(userId);
        // 商品详情start------------------------------------
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setUserId(userId);
        orderDetail.setSkuId(goodsDetail.getSkuId());
        orderDetail.setSkuName(goodsDetail.getSkuName());
        orderDetail.setImgUrl(goodsDetail.getSkuDefaultImg());
        orderDetail.setCreateTime(new Date());
        orderDetail.setSkuNum(1);
        // 查看商品原价
        BigDecimal price = goodsDetail.getPrice();
        orderDetail.setOrderPrice(price);
        // 秒杀价
        BigDecimal costPrice = goodsDetail.getCostPrice();
        orderDetail.setSplitTotalAmount(costPrice);
        // 优惠价
        orderDetail.setSplitActivityAmount(price.subtract(costPrice)); // 原价-秒杀价
        orderDetail.setSplitCouponAmount(new BigDecimal("0"));
        // 商品详情END------------------------------------
        orderInfo.setOrderDetails(Arrays.asList(orderDetail));
        orderInfo.setTotalAmount(costPrice);
        orderInfo.setActivityReduceAmount(costPrice);

        return orderInfo;
    }
}
